#include "printk.h"
#include "proc.h"
#include "syscallk.h"

extern void clock_set_next_event();

void user_syscall(uint64 fid, struct pt_regs *regs){
    switch (fid)
    {
        case SYS_WRITE:
            regs->a0 = sys_write(regs->a0,(const char*)regs->a1,regs->a2);
            break;

        case SYS_GETPID:
            regs->a0 = sys_getpid();
            break;
    default:
        break;
    }
}

void trap_handler(unsigned long scause, unsigned long sepc,  struct pt_regs *regs) {
    // 通过 `scause` 判断trap类型
    // 如果是interrupt 判断是否是timer interrupt
    // 如果是timer interrupt 则打印输出相关信息, 并通过 `clock_set_next_event()` 设置下一次时钟中断
    // `clock_set_next_event()` 见 4.5 节
    // 其他interrupt / exception 可以直接忽略
    if (scause & 0x8000000000000000) {
        if (scause == 0x8000000000000005) {
            //printk("[S] Supervisor Mode Timer Interrupt\n");
            clock_set_next_event();
            do_timer();
        }
    } else {
        //Detect ecall from u mode(0x8)
        if (scause == 0x0000000000000008) {
            //find ecall from u mode
            printk("[U] User Mode Syscall \n");
            printk("fid: %d\n", regs->a7);
            uint64 fid = regs->a7;
            user_syscall(fid, regs);
            regs->sepc += 4;
        } else {
            printk("exception: %x\n", scause);
        }
    }
}